package mood.su.db;

import android.content.Context;
import android.util.Log;

import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.PreparedQuery;
import com.j256.ormlite.stmt.Where;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class DaoHelper<T> {
    protected final String TAG = this.getClass().getSimpleName();
    private static SqliteOpenHelper db;
    private Dao<T, Long> dao;

    @SuppressWarnings("unchecked")
    public DaoHelper(Context context, Class<T> clazz) {
        db = new SqliteOpenHelper(context);
        try {
            dao = (Dao<T, Long>) db.getDao(clazz);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public Dao getDao(){
        return dao;
    }

    /** create a record */
    public boolean create(T entity) {
        try {
            int status = dao.create(entity);
            if (status > 0) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;

    }

    /** create a record */
    public boolean createOrUpdate(T entity) {
        try {
            Dao.CreateOrUpdateStatus couStatus = dao.createOrUpdate(entity);
            int status = couStatus.getNumLinesChanged();
            if (status > 0) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    /** create multiple records */
    public boolean create(List<T> entities) {
        for (T entity : entities) {
            create(entity);
        }
        return false;

    }

    /** create multiple records */
    public boolean createOrUpdate(List<T> entities) {
        boolean isSave = false;
        for (T entity : entities) {
            isSave = createOrUpdate(entity);
        }
        return isSave;

    }

    /** delete a record */
    public boolean delete(T entity) {
        try {
            int status = dao.delete(entity);
            if (status > 0) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    /** delete multiple records */
    public boolean delete(List<T> entities) {
        try {
            int status = dao.delete(entities);
            if (status > 0) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    /** delete all records */
    public boolean deleteAll() {
        try {
            int status = dao.delete(queryForAll());
            if (status > 0) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    /** delete a record by id */
    public boolean deleteById(Long id) {
        try {
            int status = dao.deleteById(id);
            if (status > 0) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;

    }

    /** delete several records by id */
    public boolean deleteIds(List<Long> ids) {
        try {
            int status = dao.deleteIds(ids);
            if (status > 0) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;

    }

    /** update a record */
    public boolean update(T entity) {
        try {
            int status = dao.update(entity);
            if (status > 0) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    /** update multiple records */
    public boolean update(List<T> entities) {
        for (T entity : entities) {
            update(entity);
        }
        return false;

    }

    /** update by id */
    public boolean updateId(T entity, Long id) {
        try {
            int status = dao.updateId(entity, id);
            if (status > 0) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;

    }

    /** query all records */
    public List<T> queryForAll() {
        List<T> all = null;
        try {
            all = dao.queryForAll();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null != all ? all : null;

    }

    /** query by ud */
    public T queryForId(Long id) {
        T entity = null;
        try {
            entity = dao.queryForId(id);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null != entity ? entity : null;

    }

    /** query multiple records */
    public List<T> queryForEq(String fieldName, String value) {
        List<T> entities = null;
        try {
            entities = dao.queryForEq(fieldName, value);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null != entities ? entities : null;

    }

    public List<T> query(PreparedQuery<T> preparedQuery) {
        List<T> entities = null;
        try {
            entities = dao.query(preparedQuery);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null != entities ? entities : null;

    }

    /** query by page */
    public List<T> queryPaging(long page, long pageSize) {
        List<T> entities = null;
        try {
            entities = query(dao.queryBuilder().limit(pageSize)
                    .offset(page * pageSize).prepare());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null != entities ? entities : null;
    }

    public boolean executeRawNoArgs(String sql) {
        int rawResult;
        try {
            rawResult = dao.executeRawNoArgs(sql);
            if (rawResult > 0) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    public boolean executeRaw(String sql, String... str) {
        int rawResult;
        try {
            rawResult = dao.executeRaw(sql, str);
            if (rawResult > 0) {
                return true;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }
}
